#include "ListeChainee.h"
#include "Iterator.h"

ListeChainee::ListeChainee(int (*fonctionTri)(void * , void *))
{
    this->tri = fonctionTri;
    debut = NULL;
    taille = 0;
}

ListeChainee::~ListeChainee(){
    Iterator it = iterator();

	while(it.hasNext()){
	    remove(it.next());
   }

}
/*
ListeChainee::ListeChainee(AbstractTri*tri , void *value)
{
    this->tri = tri;
    struct noeud* n = new noeud;
    n->suivant = NULL;
    n->value = value;
    debut = n;
}
*/
void ListeChainee::add(void * value){
    struct noeud* n = new noeud;
    n->suivant = NULL;
    n->value = value;

    struct noeud* act = debut;
    struct noeud* precedent = NULL;

    taille++;
    //si on doit ajouter au debut
    if(act == NULL || tri(value , act->value) <= 0)
    {
        n->suivant = debut;
        debut = n;
        return;
    }

    //si non on parcourt tant qu'on a pas atteind le noeud viser
    while(act != NULL && tri(value , act->value) > 0){
        precedent = act;
        act = act->suivant;
    }

    n->suivant =  act;
    precedent->suivant = n;
}

void * ListeChainee::remove(void *value){
    //on va pacourir la liste et quand on trouve le noeud a supprimer on le supprime
    struct noeud* act = debut;
    struct noeud* precedent = NULL;
    //on fait une comparaison avec les pointeur pour etre sur que l'on supprimer le bon objet
    while(act !=  NULL && value != act->value){
        precedent = act;
        act = act->suivant;
    }
    //si act == NULL on n'a pas trouver l'ellement a supprimmer donc on quite sans rien faire
    if(act == NULL){
        return NULL;
    }
    //si precedent est nul c'est qu'on traite le cas ou on supprime le premier noeud
    if(precedent == NULL)
        debut = debut->suivant;
    else
        precedent->suivant = act->suivant;

    //on stock la valeur que l'on va devoir renvoyer a l'utilisateur
    void *retour = act->value;
    //on supprime le noeud
    delete act;

    taille--;

    return retour;

}

 //retourne un iterator sur la lise
Iterator ListeChainee::iterator(){
    Iterator i;
    i.setDebut(this->debut);
    return i;
}

 bool ListeChainee::empty(){
     return debut == NULL;
 }

int ListeChainee::size(){
    return taille;
}

 /**
            _
           /x \
    1   - 3 4 5 6     NULL
     \ 2 /       \ 7 /
 **/
